package com.kevin.data;

import java.io.IOException;
import javax.sql.DataSource;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

import com.kevin.datasource.Environment;
import com.kevin.session.Configuration;
import com.kevin.session.SqlSessionFactory;
import com.kevin.session.SqlSessionFactoryBuilder;
import com.kevin.transaction.TransactionFactory;

public class SqlSessionFactoryBean
		implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
	private Configuration configuration;
	private DataSource dataSource;
	private SqlSessionFactory sqlSessionFactory;
	private String environment = SqlSessionFactoryBean.class.getSimpleName();
	private TransactionFactory transactionFactory;
	private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

	public Configuration getConfiguration() {
		return configuration;
	}

	public void setConfiguration(Configuration configuration) {
		this.configuration = configuration;
	}

	public DataSource getDataSource() {
		return dataSource;
	}

	public void setDataSource(DataSource dataSource) {
		if (dataSource instanceof TransactionAwareDataSourceProxy) {
			this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
		} else {
			this.dataSource = dataSource;
		}
	}

	@Override
	public void onApplicationEvent(ApplicationEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void afterPropertiesSet() throws Exception {
		this.sqlSessionFactory = buildSqlSessionFactory();

	}

	@Override
	public SqlSessionFactory getObject() throws Exception {
		if (this.sqlSessionFactory == null) {
			afterPropertiesSet();
		}

		return this.sqlSessionFactory;
	}

	@Override
	public Class<?> getObjectType() {
		return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

	public void setTransactionFactory(TransactionFactory transactionFactory) {
		this.transactionFactory = transactionFactory;
	}

	protected SqlSessionFactory buildSqlSessionFactory() throws IOException {

		Configuration configuration = new Configuration();

		if (this.transactionFactory == null) {
			this.transactionFactory = new SpringManagedTransactionFactory();
		}
		Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
		configuration.setEnvironment(environment);

		return this.sqlSessionFactoryBuilder.build(configuration);
	}
}
